import { Injectable } from '@angular/core'
import { Http, Response } from '@angular/http'
import { Router } from '@angular/router'
import { Action, Store } from '@ngrx/store'
import { Effect, Actions, ofType } from '@ngrx/effects'
import { Observable } from 'rxjs/Observable'
import { NzMessageService } from 'ng-zorro-antd'
import { of } from 'rxjs/observable/of'
import { mergeMap, map, tap, catchError } from 'rxjs/operators'
import * as fromRoot from '../reducers'
import * as fromUserAction from '../actions/user'
import * as fromChecklistAction from '../actions/checklist'
import { IError } from '../models/error'
import { Functions } from '../../common/functions'

@Injectable()
export class UserEffects {

  @Effect()
  refreshTokenSuccess$ = this._actions$.pipe(
    ofType<fromUserAction.RefreshTokenSuccessAction>(fromUserAction.UserActionTypes.RefreshTokenSuccess),
    map((action) => new fromChecklistAction.FetchChecklistAction(action.payload.id))
  )

  // 传token获取已登录用户(强制刷新时用)
  @Effect()
  fetchUser$ = this._actions$.pipe(
    ofType<fromUserAction.FetchCurrentUserAction>(fromUserAction.UserActionTypes.FetchCurrentUser),
    mergeMap((action) =>
      this._http.get(`api/user`, this._funcs.getRequestOptions()).pipe(
        map((res) =>
          new fromUserAction.FetchUserSuccessAction(this._funcs.parseData(res))
        ),
        catchError((err) => new Observable(() => {
          const { msg } = this._funcs.handleHttpError(err)
          this._message.error(msg)
        }))
      )
    )
  )

  @Effect()
  fetchUserSuccess$ = this._actions$.pipe(
    ofType<fromUserAction.FetchUserSuccessAction>(fromUserAction.UserActionTypes.FetchUserSuccess),
    map((action) => new fromChecklistAction.FetchChecklistAction(action.payload.id))
  )

  //#region LOGIN!
  @Effect()
  login$ = this._actions$.pipe(
    ofType<fromUserAction.LoginAction>(fromUserAction.UserActionTypes.Login),
    mergeMap((action) =>
      this._http.post(`api/user/auth`, { ...action.payload, grantType: 'password' }).pipe(
        map((res) =>
          new fromUserAction.LoginSuccessAction(this._funcs.parseData(res))
        ),
        catchError((err) => of(
          new fromUserAction.LoginFailureAction(this._funcs.handleHttpError(err))
        ))
      )
    )
  )

  @Effect()
  loginSuccess$ = this._actions$.pipe(
    ofType<fromUserAction.LoginSuccessAction>(fromUserAction.UserActionTypes.LoginSuccess),
    map((action) => new fromChecklistAction.FetchChecklistAction(action.payload.id)),
    tap(() => this._router.navigate(['/']))
  )

  @Effect({ dispatch: false })
  logout$ = this._actions$.pipe(
    ofType<fromUserAction.LogoutAction>(fromUserAction.UserActionTypes.Logout),
    tap(() => this._router.navigate(['/login']))
  )

  @Effect({ dispatch: false })
  loginFailure$ = this._actions$.pipe(
    ofType<fromUserAction.LoginFailureAction>(fromUserAction.UserActionTypes.LoginFailure),
    tap((action) => {
      const { code, msg }: IError = action.payload
      if (code && code === 4003) {
        this._message.error('用户名或密码输入有误')
      } else {
        this._message.error(msg)
      }
    })
  )
  //#endregion

  //#region REGISTER!
  @Effect()
  register$ = this._actions$.pipe(
    ofType<fromUserAction.RegisterAction>(fromUserAction.UserActionTypes.Register),
    mergeMap((action) =>
      this._http.post(`api/user/register`, action.payload).pipe(
        map((res) => new fromUserAction.RegisterSuccessAction()),
        catchError((err) => of(new fromUserAction.RegisterFailureAction(this._funcs.handleHttpError(err))))
      )
    )
  )

  @Effect({ dispatch: false })
  registerSuccess$ = this._actions$.pipe(
    ofType<fromUserAction.RegisterSuccessAction>(fromUserAction.UserActionTypes.RegisterSuccess),
    tap(() => this._message.success('注册成功，请登录'))
  )

  @Effect({ dispatch: false })
  registerFailure$ = this._actions$.pipe(
    ofType<fromUserAction.RegisterFailureAction>(fromUserAction.UserActionTypes.RegisterFailure),
    tap((action) => {
      const { code, msg }: IError = action.payload
      if (code && code === 2001) {
        this._message.error('该用户名已被注册')
      } else {
        this._message.error(msg)
      }
    })
  )
  //#endregion

  constructor (
    private _actions$: Actions,
    private _http: Http,
    private _router: Router,
    private _message: NzMessageService,
    private _funcs: Functions,
    private _store: Store<fromRoot.IState>
  ) { }

}
